package com.apimarket.util.kong.impl;

import com.apimarket.entity.kong.Plugin;
import com.apimarket.factory.JsonMapperFactory;
import com.apimarket.util.UrlUtil;
import com.apimarket.util.kong.KongPlugin;
import com.apimarket.util.kong.KongPluginParameters;
import com.apimarket.util.kong.KongRoute;
import com.apimarket.util.kong.KongService;
import com.apimarket.util.net.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class BaseKongPlugin extends KongPlugin {

    public BaseKongPlugin() {
    }

    public BaseKongPlugin(String baseUrl) {
        super(baseUrl);
    }

    @Override
    public Plugin addPlugin(Plugin plugin) throws IOException, URISyntaxException {
        String targetUrl = getBaseUrl() + addPath;
        UrlUtil urlUtil = new UrlUtil(new PostJsonNetContext(targetUrl, getPluginInfoMap(plugin)));
        JsonNode root = urlUtil.getJsonRoot();
        return JsonMapperFactory.getInstance().readValue(root.toString(), Plugin.class);
    }

    @Override
    public Plugin updatePlugin(Plugin plugin) throws IOException, URISyntaxException {
        String targetUrl = getBaseUrl() + updatePath + "/" + plugin.getId();
        UrlUtil urlUtil = new UrlUtil(new PatchJsonNetContext(targetUrl, getPluginInfoMap(plugin)));
        JsonNode root = urlUtil.getJsonRoot();
        return JsonMapperFactory.getInstance().readValue(root.toString(), Plugin.class);
    }

    @Override
    public void deletePlugin(String id) throws IOException, URISyntaxException {
        String targetUrl = getBaseUrl() + deletePath + "/" + id;
        UrlUtil urlUtil = new UrlUtil(new DeleteNetContext(targetUrl));
        urlUtil.getJsonRoot();
    }

    @Override
    public List<Plugin> listPlugin(Plugin plugin) throws IOException, URISyntaxException {
        Plugin.Service service = plugin.getService();
        Plugin.Route route = plugin.getRoute();
        Plugin.Consumer consumer = plugin.getConsumer();
        String targetUrl = getBaseUrl() + "/";
        if (service != null) targetUrl += service.getId() + listPath;
        else if (route != null) targetUrl += route.getId() + listPath;
        else if (consumer != null) targetUrl += consumer.getId() + listPath;
        else targetUrl += listPath;
        return getListPlugins(targetUrl);
    }

    private List<Plugin> getListPlugins(String targetUrl) throws IOException, URISyntaxException {
        UrlUtil urlUtil = new UrlUtil(new GetNetContext(targetUrl, null));
        JsonNode root = urlUtil.getJsonRoot();
        root = root.get("data");
        if (root == null) return null;
        ObjectMapper mapper = JsonMapperFactory.getInstance();
        CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, Plugin.class);
        return mapper.readValue(root.toString(), listType);
    }

    public List<Plugin> findServicePlugin(String id) throws IOException, URISyntaxException{
        String targetUrl = getBaseUrl() + KongService.listPath + "/" + id+listPath;
        UrlUtil urlUtil = new UrlUtil(new GetNetContext(targetUrl, null));
        JsonNode root = urlUtil.getJsonRoot();
        root = root.get("data");
        if (root == null) return null;
        ObjectMapper mapper = JsonMapperFactory.getInstance();
        CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, Plugin.class);
        return mapper.readValue(root.toString(), listType);
    }

    @Override
    public Plugin addPluginAndJudge(Plugin plugin, String operationType) throws IOException, URISyntaxException {
        String targetUrl = getBaseUrl() + addPath;
        NewPostJsonNetContext postJsonNetContext = new NewPostJsonNetContext(targetUrl, getPluginInfoMap(plugin));
        //UrlUtil urlUtil = new UrlUtil(new PostJsonNetContext(targetUrl, getPluginInfoMap(plugin)));
        JsonNode root = postJsonNetContext.getResultJsonAndJudge(operationType);
        return JsonMapperFactory.getInstance().readValue(root.toString(), Plugin.class);
    }

    @Override
    public List<Plugin> finRoutePlugins(String id) throws IOException, URISyntaxException {
        String targetUrl = getBaseUrl() + KongRoute.listPath + "/" + id+listPath;
        UrlUtil urlUtil = new UrlUtil(new GetNetContext(targetUrl, null));
        JsonNode root = urlUtil.getJsonRoot();
        root = root.get("data");
        if (root == null) return null;
        ObjectMapper mapper = JsonMapperFactory.getInstance();
        CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, Plugin.class);
        return mapper.readValue(root.toString(), listType);
    }

    private Map<String, Object> getPluginInfoMap(Plugin plugin) {
        Map<String, Object> params = new HashMap<>();

        params.put(KongPluginParameters.PLUGIN_NAME, plugin.getName());
        params.put(KongPluginParameters.PLUGIN_ROUTE, plugin.getRoute());
        params.put(KongPluginParameters.PLUGIN_SERVICE, plugin.getService());
        params.put(KongPluginParameters.PLUGIN_CONSUMER, plugin.getConsumer());
        params.put(KongPluginParameters.PLUGIN_CONFIG, plugin.getConfig());
        params.put(KongPluginParameters.PLUGIN_PROTOCOLS, plugin.getProtocols());
        params.put(KongPluginParameters.PLUGIN_ENABLED, plugin.isEnabled());
        params.put(KongPluginParameters.PLUGIN_TAGS, plugin.getTags());
        params.entrySet().removeIf(key -> key.getValue() == null);
        return params;
    }
}
